import { Text, View, Swiper, SwiperItem } from '@tarojs/components';
import theme from '@/theme';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import './index.scss';
import classNames from 'classnames';
import { Icon, PullView, ScrollView, Space, Button, Tag, Tab } from 'pd-taro-ui';
import Taro, { pxTransform } from '@tarojs/taro';
import { useReactive } from 'ahooks';
import CascaderItem from './CascaderItem';
import { getAncestorAndCurrent, transSelectedValueToValue, transValueToSelectedValue, useFlattenOptions } from '../Select/utils';
import { isEqual } from 'lodash';

export interface CascaderProps {
  placeholder?: string;
  value?: string | (string | number)[];
  onChange?: (value: CascaderProps['value'], selectedItems: CascaderProps['options']) => void;
  onBlur?: any;
  staticed?: boolean;
  disabled?: boolean;
  compProps?: any;

  /** 渲染标签：默认label */
  labelField?: string;
  /** 渲染值：默认value */
  valueField?: string;
  /** 是否显示为一行，默认true, 如果不设置value就不能选中 */
  inline?: boolean;
  options?: { label?: string; value?: any; disabled?: boolean; children?: CascaderProps['options']; [key: string]: any }[];
  /** 是否显示清除按钮 */
  clearable?: boolean;
  /** 是否多选, 默认false */
  multiple?: boolean;
  /** 是否拼接字符串，返回数组或字符串，默认true字符串 */
  joinValues?: boolean;
  /** 字符串拼接符号，多选默认, 单选默认- */
  delimiter?: string;

  /** 子集 是否拼接字符串，返回数组或字符串，默认true字符串,  如果设置了joinValues，这个也为true */
  childrenJoinValues?: boolean;
  /** 子集 字符串拼接符号，默认- */
  childrenDelimiter?: string;

  /** 只允许选择叶子节点， 默认true */
  onlyLeaf?: boolean;
}

/**
 *
 * 设计结构，树形结构
 * value是 选中的全部父级+自己[p1,p2,p3]
 * 主界面： tabs切换器+swiper,  每次点击勾中check就判断加一层swiper
 * @returns
 */
const Cascader = ({
  onChange,
  value,
  disabled,
  staticed,
  onBlur,
  placeholder = ' ',
  compProps,
  options = [],
  labelField = 'label',
  valueField = 'value',
  clearable = false,
  multiple = false,
  joinValues = true,
  delimiter = '',
  childrenJoinValues = true,
  childrenDelimiter = '-',
  onlyLeaf = true,
}: CascaderProps) => {
  if (!delimiter) {
    delimiter = multiple ? ',' : '-';
  }
  if (multiple && joinValues) {
    childrenJoinValues = true;
  }
  const state = useReactive({
    show: false,
    selectedValue: [] as any[][],
    searchStr: '',
  });
  const flattenOptions = useFlattenOptions(options);
  const [option2d, setOption2d] = useState<CascaderProps['options'][]>([]);
  const [swipeActiveKey, setSwipeActiveKey] = useState(0);

  const hadSelectedValue = useMemo(() => {
    let bool = false;
    if (state.selectedValue?.[0]?.length) {
      bool = true;
    }
    return bool;
  }, [state.selectedValue]);

  /** 切换下一级 */
  const toNextDeepth = (item: any, deepth: number) => {
    if (!item.children?.length) return;
    // console.log('Cascader.toNextDeepth ', { item, deepth });
    // 给下一级options赋值, 并清空后面的选中
    const newOption2d = option2d.concat();
    newOption2d.splice(deepth + 1, newOption2d.length, item.children);
    setOption2d(newOption2d);
    setTimeout(() => {
      setSwipeActiveKey(deepth + 1);
    }, 200);
  };

  const toggleCheck = (item: any, deepth: number) => {
    if (disabled) return;
    const isCheck = getIsCheck(item);
    const tempValue = item[valueField];
    // console.log('Cascader.toggleCheck ', { item, deepth, isCheck, tempValue });
    if (typeof tempValue !== 'number' && typeof tempValue !== 'string') {
      console.warn('Cascader.toggleCheck 非number和string 禁止选中', item);
      return;
    }
    if (!isCheck) {
      if (item.disabled) {
        return;
      }
      // 选中
      if (multiple) {
        if (onlyLeaf && item.children?.length) {
          Taro.showToast({
            title: '只允许选择叶子节点',
            icon: 'none',
          });
          return;
        }
        console.log('Cascader.toggleCheck 选中', { item, multiple });
        state.selectedValue = state.selectedValue.concat([getAncestorAndCurrent(item).map(v => v[valueField]) as any]);
      } else {
        if (!state.selectedValue.length) {
          state.selectedValue = [[]];
        }
        state.selectedValue[0].splice(deepth, state.selectedValue[0].length, tempValue as any);
        state.selectedValue = state.selectedValue.concat();
        toNextDeepth(item, deepth);
      }
    } else {
      // 取消选中
      if (multiple) {
        const ancestorAndCurrentValues = getAncestorAndCurrent(item, valueField).map(v => v[valueField]);
        state.selectedValue = state.selectedValue.filter(v => {
          // 先对比长度，在对比内容
          if (v.length !== ancestorAndCurrentValues.length) return true;
          return !isEqual(v, ancestorAndCurrentValues);
        });
      } else {
        state.selectedValue[0].splice(deepth, 1);
        state.selectedValue = state.selectedValue.concat();
      }
    }
  };

  const getIsCheck = (item: any) => {
    let bool = false;
    if (multiple) {
      // 判断二维字符串数组state.selectedValue 最后一级
      state.selectedValue.forEach((v: any) => {
        if (v[v.length - 1] === item[valueField]) {
          bool = true;
        }
      });
    } else {
      // 判断二维字符串数组state.selectedValue里是否包含 item[valueField]
      state.selectedValue.forEach((v: any) => {
        if (v.includes(item[valueField])) {
          bool = true;
        }
      });
    }

    return bool;
  };

  const selectedItems = useMemo(() => {
    let currentOptions: any[] = [];
    const items = state.selectedValue.map(v1 => {
      return v1.map((v2, i2) => {
        // TODO，异步查询可能找不到，后续再优化
        if (i2 === 0) {
          currentOptions = options;
        }
        const item = currentOptions?.find(v3 => v3[valueField] === v2) || {};
        // console.log('selectedItems find', { v1, v2, i2, item, currentOptions: currentOptions.concat() });
        currentOptions = item?.children || [];
        return item;
      });
    });
    // console.log('Cascader.selectedItems', { items, options });
    return items;
  }, [state.selectedValue, options, valueField]);

  const staticStr = useMemo(() => {
    return state.selectedValue
      .map(item1 => {
        return item1
          .map(item2 => {
            const item3 = flattenOptions.find(option => option[valueField] === item2);
            return item3?.[labelField] || '';
          })
          .join(childrenDelimiter);
      })
      .join(delimiter);
  }, [state.selectedValue, delimiter, childrenDelimiter, flattenOptions, labelField, valueField]);

  const open = () => {
    if (disabled) return;
    state.show = true;
    setOption2d([options]);
    setSwipeActiveKey(0);
  };
  const close = () => {
    state.show = false;
  };
  const submit = (needCheckValid: boolean = true) => {
    let submitValue: any = '';
    let submitItems: any[] = [];
    if (!multiple) {
      submitValue = state.selectedValue[0] || [];
      submitItems = selectedItems[0] || [];
      if (needCheckValid) {
        if (!submitValue?.length) {
          Taro.showToast({
            icon: 'none',
            title: '至少选中一项',
          });
          return;
        } else if (onlyLeaf && submitItems[submitItems.length - 1]?.children?.length) {
          Taro.showToast({
            icon: 'none',
            title: '必须选中最后一级',
          });
          return;
        }
      }
      submitValue = transSelectedValueToValue(submitValue, true, joinValues, delimiter);
    } else {
      submitValue = state.selectedValue;
      submitItems = selectedItems;
      submitValue = submitValue.map(v => {
        return transSelectedValueToValue(v, multiple, childrenJoinValues, childrenDelimiter);
      });
      submitValue = transSelectedValueToValue(submitValue, multiple, joinValues, delimiter);
    }

    onChange?.(submitValue.concat(), submitItems.concat());
    close();
  };
  const clear = () => {
    state.selectedValue = [];
    submit(false);
  };

  useEffect(() => {
    if (!state.show) {
      let selectedValue: any[] = [];
      if (multiple) {
        selectedValue = transValueToSelectedValue(value, multiple, joinValues, delimiter);
        selectedValue = selectedValue.map(v => {
          return transValueToSelectedValue(v, multiple, childrenJoinValues, childrenDelimiter);
        });
      } else {
        if (value?.length) {
          selectedValue = transValueToSelectedValue(value, true, joinValues, delimiter);
          selectedValue = [selectedValue];
        }
      }
      if (!isEqual(selectedValue, state.selectedValue.concat())) {
        // console.log('!state.show', JSON.stringify(selectedValue));
        state.selectedValue = selectedValue;
      }
    }
  }, [childrenDelimiter, childrenJoinValues, delimiter, joinValues, multiple, state, state.show, value]);

  // console.log('Cascader', {
  //   option2d,
  //   hadSelectedValue,
  //   selectedItems,
  //   flattenOptions,
  //   staticStr,
  //   multiple,
  //   'state.selectedValue': state.selectedValue.map(v => v.concat()),
  // });

  if (staticed) {
    return <View className='pd-cascader--static'>{staticStr}</View>;
  }
  return (
    <>
      <View className={classNames({ 'pd-cascader': true, 'pd-cascader--disabled': disabled })}>
        <View className={classNames({ 'pd-cascader__content': true })} onClick={open}>
          {multiple && hadSelectedValue ? (
            <Space row wrap gap={8}>
              {selectedItems.map((item, index) => {
                if (!item?.length) return null;
                return (
                  <Tag
                    key={index}
                    closable={!disabled}
                    onClose={e => {
                      e.stopPropagation?.();
                      state.selectedValue.splice(index, 1);
                      state.selectedValue = state.selectedValue.concat();
                      submit();
                    }}>
                    {item[item.length - 1]?.[labelField]}
                  </Tag>
                );
              })}
            </Space>
          ) : (
            <Text className={classNames({ 'pd-cascader__text': true, 'pd-cascader__placeholder': !hadSelectedValue })}>
              {staticStr || placeholder || ' '}
            </Text>
          )}
        </View>
        {clearable && !disabled && hadSelectedValue && <Icon name='error' color='#bbb' size={36} onClick={clear} />}
        <Icon name='right' color='#bbb' size={36} />
      </View>

      <PullView open={state.show} onClose={close} side='bottom'>
        <View className='pd-cascader__modal'>
          <View className='pd-cascader__modal__header'>请选择</View>
          <View className='pd-cascader__modal__close' onClick={close}>
            <Icon name='close' size={46} />
          </View>
          <Tab scroll value={swipeActiveKey} onChange={setSwipeActiveKey}>
            {option2d?.map((options1, deepth) => {
              let title = '请选择';
              if (!multiple) {
                const currentSelectedValue = state.selectedValue?.[0]?.[deepth];
                title =
                  (currentSelectedValue ? options1?.find(v => v[valueField] === currentSelectedValue)?.[labelField] : '请选择') || '请选择';
              } else {
                title = `第${deepth + 1}层`;
              }

              return <Tab.Item title={title} key={deepth} paneKey={deepth} />;
            })}
          </Tab>
          <Swiper
            className='pd-cascader__swiper'
            duration={300}
            current={swipeActiveKey}
            onChange={e => setSwipeActiveKey(e.detail.current)}
            disableTouchmove={true as any}
            disableTouch={true}>
            {option2d?.map((options1, deepth) => {
              return (
                <SwiperItem key={deepth}>
                  <View className='pd-cascader__swiper-item'>
                    <ScrollView>
                      {options1?.map((item, index) => {
                        return (
                          <CascaderItem
                            key={index}
                            getIsCheck={getIsCheck}
                            item={item}
                            labelField={labelField}
                            valueField={valueField}
                            toNextDeepth={toNextDeepth}
                            deepth={deepth}
                            toggleCheck={toggleCheck}
                            isCheckBox={multiple}></CascaderItem>
                        );
                      })}
                    </ScrollView>
                  </View>
                </SwiperItem>
              );
            })}
          </Swiper>
          <Button
            type='primary'
            style={{ width: pxTransform(300), alignSelf: 'center', marginTop: pxTransform(30) }}
            onClick={() => submit(true)}>
            确定
          </Button>
        </View>
      </PullView>
    </>
  );
};
export default Cascader;
